﻿using System;
using System.Globalization;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Cluster.LiveJournalLib;
using Microsoft.WindowsMobile;
using Microsoft.WindowsMobile.Configuration;
using Microsoft.WindowsMobile.Telephony;
using Microsoft.WindowsMobile.Forms;
using Microsoft.WindowsMobile.Status;
using Microsoft.WindowsMobile.Location;

namespace Cluster.JeJePoster
{
    public partial class PstoForm : Form
    {
        readonly LiveJournalClient ljClient;
        private Gps gps;
        readonly Event? EventInfo;
        readonly ResourceManager resources = new ResourceManager("JeJePoster.Languages", Assembly.GetExecutingAssembly());
        private readonly int textBoxTop;
        private DateTime? postTime;
        private uint? moodId = null;

        private const bool Config_AutoDetectMusic = false;
        private const bool Config_GpsAutoStart = true;

        public PstoForm(LiveJournalClient liveJournalClient, Event? eventInfo)
        {
            InitializeComponent();
            textBoxTop = textBoxBody.Top;
            buttonSelectGroups.Height = comboBoxSecurity.Height;
            buttonSelectTags.Height = textBoxTags.Height;
            buttonDetectMusic.Height = textBoxMusic.Height;
            ljClient = liveJournalClient;
            ljClient.LoadData(false);
            EventInfo = eventInfo;
            LoadUserData();
            if (eventInfo == null)
            {
                comboBoxJournal.SelectedIndex = 0;
                comboBoxUserpic.SelectedIndex = 0;
                comboBoxSecurity.SelectedIndex = 0;
                comboBoxComments.SelectedIndex = 0;
                comboBoxScreening.SelectedIndex = 0;
                comboBoxAdult.SelectedIndex = 0;
                postTime = null;
                if (Config_GpsAutoStart)
                {
                    checkBoxCoords.Checked = true;
                    checkBoxGPS.Checked = true;
                }
                textBoxCoords.ReadOnly = !(checkBoxCoords.Checked && !checkBoxGPS.Checked);
                gpsUpdateState();
            } else
            {
                gps = null;
            }
            UpdateDate();
        }

        void LoadUserData()
        {
            comboBoxJournal.Items.Clear();
            comboBoxJournal.Items.Add(ljClient.User);
            foreach (var journal in ljClient.Journals)
                comboBoxJournal.Items.Add(journal);

            comboBoxUserpic.Items.Clear();
            comboBoxUserpic.Items.Add(resources.GetString("Default"));
            foreach (var picture in ljClient.Pictures)
            {
                comboBoxUserpic.Items.Add(picture.keyword);
            }

            comboBoxMoods.Items.Clear();
            var moods = new List<string>();
            foreach (var mood in ljClient.Moods)
                moods.Add(mood.Value);
            moods.Sort();
            foreach (var mood in moods)
            {
                comboBoxMoods.Items.Add(mood);
            }
        }

        void gpsStart()
        {
            if (gps == null) gps = new Gps();
            gps.DeviceStateChanged += gps_DeviceStateChanged;
            gps.LocationChanged += gps_LocationChanged;
            gps.Open();
        }
        void gpsStop()
        {
            if (gps != null) gps.Close();
        }
        void gpsUpdateState()
        {
            try
            {
                if (checkBoxGPS.Checked) gpsStart();
                else gpsStop();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,
                                resources.GetString("Error"), MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation,
                                MessageBoxDefaultButton.Button1);
            }
        }

        Image ResizeImage(Image inputImg, int width, int height)
        {
            int nheight = height;
            int nwidth = width;
            if ((inputImg.Width <= width) && (inputImg.Height <= height))
            {
                nwidth = inputImg.Width;
                nheight = inputImg.Height;
            }
            else
            {
                if (inputImg.Width / inputImg.Height > width / height)
                {
                    nheight = nheight * inputImg.Height / inputImg.Width;
                }
                else
                {
                    nwidth = nwidth * inputImg.Width / inputImg.Height;
                }
            }
            var outputImg = new Bitmap(nwidth, nheight);
            Graphics graphics = Graphics.FromImage(outputImg);
            var brush = new SolidBrush(this.ForeColor);
            graphics.FillRectangle(brush, 0, 0, width, height);
            graphics.DrawImage(inputImg, new Rectangle(0, 0, nwidth, nheight),
                new Rectangle(0, 0, inputImg.Width - 1, inputImg.Height - 1), GraphicsUnit.Pixel);
            return outputImg;
        }
        void LoadPicture()
        {
            string picPath = "";
            if (comboBoxUserpic.SelectedIndex == 0)
                picPath = ljClient.DefaultPictureFile;
            else
            {
                foreach (var picture in ljClient.Pictures)
                {
                    if (picture.keyword == comboBoxUserpic.Text)
                        picPath = picture.fileName;
                }
            }
            Bitmap bitmap;
            try
            {
                bitmap = new Bitmap(picPath);
            }
            catch
            {
                bitmap = new Bitmap(100, 100);
            }
            pictureBoxUserpic.Image = ResizeImage(Image.FromHbitmap(bitmap.GetHbitmap()), pictureBoxUserpic.Width, pictureBoxUserpic.Height);
        }

        private void comboBoxUserpic_SelectedIndexChanged(object sender, EventArgs e)
        {
            LoadPicture();
        }

        private void PstoForm_Closed(object sender, EventArgs e)
        {
            gpsStop();
            if (EventInfo == null) Application.Exit();
        }

        private void DetectMusic()
        {
            try
            {
                if (!string.IsNullOrEmpty(SystemState.MediaPlayerTrackTitle))
                {
                    textBoxMusic.Text = (!string.IsNullOrEmpty(SystemState.MediaPlayerTrackArtist)
                                             ? (SystemState.MediaPlayerTrackArtist + " - ")
                                             : "") + SystemState.MediaPlayerTrackTitle;
                }
            }
            catch { }
        }

        private void UpdateDate()
        {
            if (postTime == null)
            {
                labelDateTime.Text = resources.GetString("Date") + DateTime.Now;
            }
        }

        private void timerUpdate_Tick(object sender, EventArgs e)
        {
            UpdateDate();
            if (Config_AutoDetectMusic)
            {
                DetectMusic();
            }
            try
            {
                if (checkBoxGPS.Checked) PowerControl.SystemIdleTimerReset();
            }
            catch
            {
            }
        }

        private void buttonDetectMusic_Click(object sender, EventArgs e)
        {
            DetectMusic();
        }

        private void comboBoxMoods_SelectedIndexChanged(object sender, EventArgs e)
        {
            moodId = ljClient.GetMoodId(comboBoxMoods.Text);
            if (moodId != null)
            {
                checkBoxMoodIcon.Enabled = true;
                checkBoxMoodIcon.Checked = true;
            }
        }

        private void InsertTags(string insLeft, string insRight)
        {
            int SelectionStart = textBoxBody.SelectionStart;
            int SelectionLength = textBoxBody.SelectionLength;
            textBoxBody.Text =
                textBoxBody.Text.Insert(SelectionStart + SelectionLength, insRight).Insert(
                SelectionStart, insLeft);
            if (SelectionLength > 0)
            {
                textBoxBody.SelectionStart = SelectionStart;
                textBoxBody.SelectionLength = SelectionLength + insLeft.Length + insRight.Length;
            } else
            {
                textBoxBody.SelectionStart = SelectionStart + SelectionLength + insLeft.Length + insRight.Length;
                textBoxBody.SelectionLength = 0;
            }
            textBoxBody.ScrollToCaret();
        }

        private void pictureButtonBold_Click(object sender, EventArgs e)
        {
            InsertTags("<b>", "</b>");
        }

        private void pictureButtonItalian_Click(object sender, EventArgs e)
        {
            InsertTags("<i>", "</i>");
        }

        private void pictureButtonUnderline_Click(object sender, EventArgs e)
        {
            InsertTags("<u>", "</u>");
        }

        private void pictureButtonStrike_Click(object sender, EventArgs e)
        {
            InsertTags("<strike>", "</strike>");
        }

        private void pictureButtonLJuser_Click(object sender, EventArgs e)
        {
            var friendSelectForm = new FriendSelectForm(ljClient.Friends);
            if (friendSelectForm.ShowDialog() == DialogResult.OK)
                InsertTags("", friendSelectForm.GetSelectedFriends());
            friendSelectForm.Dispose();
        }

        private void timerEnlargeTextBox_Tick(object sender, EventArgs e)
        {
            if (textBoxBody.Top > 18)
            {
                textBoxBody.Top -= 15;
                textBoxBody.Height += 15;
            }
            else if (textBoxBody.Top > 3)
            {
                textBoxBody.Top -= 5;
                textBoxBody.Height += 5;
            }
            else
            {
                timerEnlargeTextBox.Enabled = false;
                pictureButtonArrowDown.Visible = true;
            }
        }

        private void timerEnlargeTextBoxReverse_Tick(object sender, EventArgs e)
        {
            if (textBoxBody.Top < textBoxTop - 15)
            {
                textBoxBody.Top += 15;
                textBoxBody.Height -= 15;
            } else if (textBoxBody.Top < textBoxTop)
            {
                textBoxBody.Top += 5;
                textBoxBody.Height -= 5;
            }
            else
            {
                timerEnlargeTextBoxReverse.Enabled = false;
                pictureButtonArrowUp.Visible = true;
            }
        }

        private void pictureButtonPhoto_Click(object sender, EventArgs e)
        {
        }

        private void textBoxBody_LostFocus(object sender, EventArgs e)
        {
            timerEnlargeTextBoxReverse.Enabled = true;
        }

        private void pictureButtonArrowUp_MouseDown(object sender, MouseEventArgs e)
        {
            timerEnlargeTextBox.Enabled = true;
            timerEnlargeTextBoxReverse.Enabled = false;
            pictureButtonArrowUp.Visible = false;
        }

        private void pictureButtonArrowDown_MouseDown(object sender, MouseEventArgs e)
        {
            timerEnlargeTextBoxReverse.Enabled = true;
            pictureButtonArrowDown.Visible = false;
        }

        private delegate void UpdateCoordsDelegate(string coords, string gpsStats);
        private void UpdateCoords(string coords, string gpsStats)
        {
            if (!string.IsNullOrEmpty(coords)) textBoxCoords.Text = coords;
            labelGpsStats.Text = gpsStats;
        }

        protected void gps_LocationChanged(object sender, LocationChangedEventArgs args)
        {
            /// Latitude in decimal degrees.  North is positive
            /// Longitude in decimal degrees.  East is positive
            GpsPosition position = args.Position;
            if (position == null)
            {
                Invoke(new UpdateCoordsDelegate(UpdateCoords), new object[] { null, resources.GetString("SatelliteCount") + ": 0/0" });
                return;
            }
            try
            {
                string coords = null;
                var satelliteStats = new StringBuilder();
                satelliteStats.Append(resources.GetString("SatelliteCount") + ": ");
                if ((position.LatitudeValid) && (position.LongitudeValid))
                {
                    var nfi = new NumberFormatInfo {NumberDecimalSeparator = "."};
                    coords = ((position.Latitude > 0)
                                  ? ("N" + position.Latitude.ToString(nfi))
                                  : ("S" + (-position.Latitude).ToString(nfi))) +
                             " " +
                             ((position.Longitude > 0)
                                  ? ("E" + position.Longitude.ToString(nfi))
                                  : ("W" + (-position.Longitude).ToString(nfi)));
                }

                // Satellite stats
                Satellite[] satellitesInSolution = position.GetSatellitesInSolution();
                satelliteStats.Append((satellitesInSolution ?? new Satellite[] {}).Length + "/" +
                                      (position.SatellitesInViewValid ? position.SatellitesInViewCount : 0));
                Satellite[] satellitesInView = position.GetSatellitesInView();
                if (satellitesInView != null)
                    foreach (var satellite in satellitesInView)
                    {
                        bool inSolution = false;
                        if (satellitesInSolution != null)
                            foreach (var satelliteInSolution in satellitesInSolution)
                                if (satelliteInSolution.Id == satellite.Id) inSolution = true;
                        satelliteStats.Append("\r\n" + (inSolution ? "* " : "") +
                                              resources.GetString("Satellite") +
                                              " " +
                                              satellite.Id + " - " + resources.GetString("SignalStrenght") +
                                              ": " +
                                              satellite.SignalStrength);
                    }
                Invoke(new UpdateCoordsDelegate(UpdateCoords), new object[] {coords, satelliteStats.ToString()});
            }
            catch
            {
            }
        }

        void gps_DeviceStateChanged(object sender, DeviceStateChangedEventArgs args)
        {
            var device = args.DeviceState;
            if ((device != null) && (device.DeviceState != GpsServiceState.On))
                Invoke(new UpdateCoordsDelegate(UpdateCoords),
                       new object[] {null, resources.GetString("GpsState") + ": " + device.DeviceState});
        }

        private void checkBoxCoords_CheckStateChanged(object sender, EventArgs e)
        {
            if (!checkBoxCoords.Checked) checkBoxGPS.Checked = false;
            textBoxCoords.ReadOnly = !(checkBoxCoords.Checked && !checkBoxGPS.Checked);
            if (!checkBoxGPS.Checked && (textBoxCoords.Text == "???")) textBoxCoords.Text = "";
            gpsUpdateState();
        }

        private void checkBoxGPS_CheckStateChanged(object sender, EventArgs e)
        {
            gpsUpdateState();
            if (checkBoxGPS.Checked) checkBoxCoords.Checked = true;
            textBoxCoords.ReadOnly = !(checkBoxCoords.Checked && !checkBoxGPS.Checked);
            if (!checkBoxGPS.Checked && (textBoxCoords.Text == "???")) textBoxCoords.Text = "";
            if (checkBoxGPS.Checked) textBoxCoords.Text = "???";
        }

    }
}